const Mock = require('mockjs');
const colors = require('colors');
const path = require('path');
const express = require('express');
const bodyParser = require('body-parser')
const httpProxy = require('http-proxy-middleware');

const { readFiles, getLog } = require('./utils');

const app = express();

colors.setTheme({
    silly: 'rainbow',
    input: 'grey',
    info: 'green',
    help: 'cyan',
    warn: 'yellow',
    debug: 'blue',
    error: 'red'
});



class Server {
    // port;端口号
    // host;地址
    // mockPath;mock读取地址 
    // proxyPath; 代理路径
    // mocks; 所有mock对象
    // errorMock; 注册失败的mock
    // log; 日志打印方法
    constructor(argv) {
        this.argv = argv;
        this.port = argv.port;
        this.host = argv.host;
        this.proxyPath = argv.proxyPath;
        this.mockPath = path.join(process.cwd(), argv.mockPath);
        this.mocks = {};
        this.errorMock = {};

        const logPath = argv.logPath;
        if (logPath) {
            this.log = getLog(logPath);
        } else {
            this.log = () => {}
        }
    }


    init() {
        if (this.proxyPath) {
            this.proxy();
        } else {
            app.use(bodyParser.json()); // for parsing application/json
            app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
            this.local();
        }

    }

    // 代理模式
    proxy() {
        // 代理配置
        const proxy = httpProxy('/', {
            target: this.proxyPath,
            changeOrigin: true,
            pathRewrite: {
                '/': '/'
            },
            // 监听代理请求
            onProxyReq: (proxyReq, req, res) => {
                const reqInfo = this.setReqInfo(req);
                console.log(`[${reqInfo.time.red}] [${reqInfo.ip.cyan}] 请求 ${reqInfo.url.magenta} ${reqInfo.ua}`);
                this.log(` ${reqInfo.ip} 请求 ${reqInfo.url} ${reqInfo.ua}`);
            },
            // 监听代理响应
            onProxyRes: (proxyRes, req, res) => {}
        });
        app.use(proxy);
        this.start();
    }

    // 本地模式
    local() {
        // 读取所有文件
        readFiles(this.mockPath, (filesPaths) => {
            filesPaths.forEach(filesPath => {
                let mockObj = require(filesPath);
                Object.keys(mockObj).forEach(api => {
                    if (this.mocks[api]) {
                        this.errorMock[api] = filesPath;
                        return;
                    } else {
                        // 将mock保存在mocks中
                        this.mocks[api] = mockObj[api];
                    }

                    app.all(api, (req, res) => {
                        let reqInfo = this.setReqInfo(req);
                        console.log(`[${reqInfo.time.red}] [${reqInfo.ip.cyan}] ${reqInfo.url.magenta} ${reqInfo.ua}`);
                        let template = mockObj[api];
                        let response;
                        // 如果是方法
                        if (typeof template === 'function') {
                            response = Mock.mock(template(req.body));
                        } else {
                            response = Mock.mock(template);
                        }
                        // 如果mock语法解析后为undefined的处理
                        response = response || {};
                        // mock配置项。目前只支持delay
                        let config = response.mockConfig;
                        if (config) {
                            let { delay } = config;
                            setTimeout(() => {
                                res.json(response);
                            }, delay);
                        } else {
                            res.json(response);
                        }
                    });
                })
            });

            this.start();
        });
    }


    // 设置请求信息
    setReqInfo(req) {
        let now = new Date();
        return {
            time: now.toLocaleDateString() + ' ' + now.toLocaleTimeString(),
            url: req.url,
            ip: req.ip,
            ua: req.get('user-agent')
        }
    }

    // 服务开启
    start() {
        app.listen(this.port, this.host, () => {
            if (!this.proxyPath) {
                console.log(colors.silly('****************************************************************'));
                console.log(`  本地模式已启动 {"接口数量": ${colors.info(Object.keys(this.mocks).length)}，"端口号": ${colors.info(this.port)}}`);
                console.log(colors.silly('****************************************************************'));
                let errors = Object.keys(this.errorMock);
                if (errors.length) {
                    console.log(colors.warn(`  注册失败接口 {"接口数量":${errors.length}}`));
                    errors.forEach(api => {
                        console.log(`{"接口名称": ${api}, "所在文件": ${this.errorMock[api]}}`);
                    })
                }
            } else {
                console.log(colors.silly('****************************************************************'));
                console.log(`  代理模式已启动 {"端口号": ${colors.info(this.port)}}`);
                console.log(colors.silly('****************************************************************'));
            }

        })
    }
}



module.exports = Server;